/**
 * Copyright (c) 2009 Koder Chen. All Rights Reserved.
 *
 * bigint.h
 * The file declares the basic operations needed to manipulate the big integer,
 * including the add, minus, multiply, and so, on
 *
 *  Author: chenfuhan
 * Created: 2009-6-1
 * Version: 1.0
 */
#ifndef __RSA_BIGINT_H__
#define __RSA_BIGINT_H__

#include "type.h"

// some predifined constant
// the maximum of the bits for a big integer
extern i32_t MAX_BITS;
extern i32_t MAX_BYTES;

extern u8_pt bi_mod_t;
extern u8_pt bi_mul_t;
extern u8_pt bi_div_pt;
extern u8_pt bi_div_qt;

// the global bits array
extern const u32_t BITS[9];

/**
 * used to add two big integer together.
 *
 * @param a the first addend
 * @param b the augend
 * @param out the output holder
 */
void bi_add(u8_pt a, u8_pt b, u8_pt out);

/**
 * used to subtract b from a, who are all bigintegters
 *
 * @param a the minuend
 * @param b the subtrahend
 * @param out the output holder
 */
void bi_sub(u8_pt a, u8_pt b, u8_pt out);

/**
 * used to multiply a and b, who are all bigintegters
 *
 * @param a the faciend
 * @param b the multiplier
 * @param out the output holder
 */
void bi_mul(u8_pt a, u8_pt b, u8_pt out);

/**
 * used to divide b from a, who are all bigintegters
 *
 * @param a the dividend
 * @param b the divisor
 * @param quot the quotient output holder
 * @param rema the remainder holder
 */
void bi_div(u8_pt a, u8_pt b, u8_pt quot, u8_pt rema);

/**
 * used to get the modules of a to b.
 *
 * @param a the passed in integer
 * @param b the the module basic
 * @param out the output holder
 */
void bi_mod(u8_pt a, u8_pt b, u8_pt out);

/**
 * used to calculate the module of a^b to n.
 *
 * @param a the basic of the power
 * @param b the power
 * @param n the module basic
 * @param out the output holder
 */
void bi_powm(u8_pt a, u8_pt b, u8_pt n, u8_pt out);

/**
 * used to calculate the gcd of a and b
 *
 * @param a the first integer
 * @param b the second integer
 * @param out the output holder
 */
void bi_gcd(u8_pt a, u8_pt b, u8_pt out);

/**
 * used to left shift n-bits of the integer
 *
 * @param a the integer to be shifted
 * @param b the number of bits to shift the interger
 * @param out the output holder
 */
void bi_lshift(u8_pt a, i32_t bits);

/**
 * used to right shift n-bits of the integer
 *
 * @param a the integer to be shifted
 * @param b the number of bits to shift the interger
 * @param out the output holder
 */
void bi_rshift(u8_pt a, i32_t bits);

/**
 * used to compare two big integers
 *
 * @param a first integer to be compared
 * @param b second integer to be compared
 * @return 0 if the two are equal, or -1 if a<b, or 1 if a>b
 */
 i32_t bi_comp(u8_pt a, u8_pt b);
 
 /**
  * used to set the specified bit's value to the specified one
  *
  * @param a the big integer to be set
  * @param pos the position or index of the bit of the integer to be set
  * @param v the value, it should be 1 or 0
  */
 void bi_set_bit(u8_pt a, i32_t pos, i32_t v);
 
 /**
  * used to fetch the specified position's bit's value for the integer
  *
  * @param a the big integer to be set
  * @param pos the position or index of the bit of the integer to be getted
  * @return 1 if the specified position is 1, or 0 otherwise
  */
 i32_t bi_get_bit(u8_pt a, i32_t pos);
 
 /**
  * used to copy some bits from 'src' to 'dst'.
  *
  * @param dst the destination of the copy action. i.e. where do the bits will be copied
  *            to
  * @param src the source of the bits, i.e. where do the bits come from
  * @param start the start position
  * @param bits the number of bits to be copied
  */
 void bi_copy_bits(u8_pt dst, u8_pt src, i32_t start, i32_t bits);
 
 /**
  * used to copy some bytes from 'src' to 'dst'.
  *
  * @param dst the destination of the copy action. i.e. where do the bytes will be copied
  *            to
  * @param src the source of the bytes, i.e. where do the bytes come from
  * @param start the start point of the copy action for the source
  * @param bytes the number of bytes to be copied
  */
 void bi_copy_bytes(u8_pt dst, u8_pt src, i32_t start, i32_t bytes);
 
 /**
  * used to fetch the valid number of bits of big integer a
  *
  * @param a the big integer to be checked
  * @return the number of bits
  */
 i32_t bi_bits(u8_pt a);
 
 /**
  * used to reset an array, that means, reset the array to whole zero
  *
  * @param a the array to be reset
  */
 void bi_reset(u8_pt a);

 i32_t bi_bytes(u8_pt a);
 
#endif // __RSA_BIGINT_H__
